#!/usr/bin/python3
# -*- coding:utf-8 -*-
""""
   @Author: 即将拥有人鱼线的yjw
   @Time: 2023/11/30 17:08
   @File: BasicCommonMethods.py
   @desc:
"""
import os
import re
import time
import traceback

from qturboframe.lib.webdriver.exceptions import SeleniumError
from qturboframe.lib.utils.variable import Variable

from AmlScripts.amlConfig import amlConfig
from AmlScripts.BasicFunction.common_test_prepare import (common_test_prepare, sql_handle_class, check_result,
                                                          catch_exceptions, test_db_link)
from AmlScripts.BasicFunction.env_check import change_company, check_server
from BladeFerm.Lib.Common import DownPath, logger, data_processing
from BladeFerm.databases.DealSql.EnvConfig import EnvConfig
from BladeFerm.hui12_common.check_data import check_file_exit
from BladeFerm.hui2_app.basic import sys_login, FE
from BladeFerm.utils.FileOerate import getFilePath
from BladeFerm.utils.DataUtil import dataUtil
from BladeFerm.utils.OperationExcel import getExcelData
from BladeFerm.utils.OperationExcel import ExcelVarles
from BladeFerm.utils.basic_opration import delete_dir_file
from BladeFerm.databases import DB_APP

from CommonScripts.check_result_hui_two import check_table
from CommonScripts.common_method_hui_two import open_menu, tab_click, arm_form_fill


def bak_uam_company(env: str):
    """
    备份uam_company表
    :param env:
    :return:
    """
    if re.search(r"mysql|pg", env):
        sql = f"SELECT count(1) as TOTAL FROM information_schema.tables WHERE table_schema = 'hspbs' AND table_name = 'UAM_COMPANY_BAK'"
    else:
        sql = f"SELECT COUNT(*) AS TOTAL FROM SYS.ALL_TAB_COLUMNS WHERE table_name = 'UAM_COMPANY_BAK'"
    result = DB_APP.run_one_sql(sql)
    if result and result[0].get("TOTAL") == 0:
        # sql2 = f"drop TABLE hspbs.uam_company_bak"
        DB_APP.run_one_sql("CREATE TABLE hspbs.uam_company_bak like hspbs.uam_company")
    DB_APP.run_one_sql("delete from hspbs.uam_company_bak where 1=1")
    DB_APP.run_one_sql("insert into hspbs.uam_company_bak select * from hspbs.uam_company")
    logger.info(f"备份uam_company表成功")


@test_db_link
@catch_exceptions
def change_company_no(input_data=None, ui_expect=None):
    """
    切换公司号
    :param input_data: { 'company_no' '0', 'company_name': '恒生电子', 'env': 'oracle', 'operation': 'modify|recover'}
    :param ui_expect:
    :return:
    """
    def __chang_company_no(company_no, company_name, env):
        logger.info(f"开始切换公司号为{company_no}")
        act_result = change_company(company_no=company_no, company_name=company_name, env=env)
        logger.info(f"切换公司号{company_no}完成，执行结果是：{act_result}")
        check_result(act_result)
        return True
    new_company_no = input_data.get("company_no", "0")
    new_company_name = input_data.get("company_name", "恒生电子")
    env_name = input_data.get("env", "oracle")
    operation = input_data.get("operation", "modify")
    config = amlConfig.get(env_name)
    logger.info(f"{config} 环境的系统参数是：{config}")
    logger.info(f"切换公司号：{input_data}，ui_expect： {ui_expect}")
    # 检查当前环境的公司号
    sql = f"select company_no, company_name from hspbs.uam_company"
    result = DB_APP.run_one_sql(sql)
    logger.info(f"当前公司号：{result}")
    if operation == "modify":
        bak_uam_company(env_name)
        if result and result[0].get("COMPANY_NO") == str(new_company_no):
            logger.info(f"公司号为{new_company_no}，无需切换！")
        else:
            __chang_company_no(new_company_no, new_company_name, env_name)
    else:
        sql2 = f"select company_no, company_name from hspbs.uam_company_bak"
        result_bak = DB_APP.run_one_sql(sql2)
        logger.info(f"备份的公司号：{result_bak}")
        new_company_no = result_bak[0].get("COMPANY_NO")
        if result[0].get("COMPANY_NO") == new_company_no:
            logger.info(f"公司号为{new_company_no}，无需切换！")
        else:
            new_company_name = result_bak[0].get("COMPANY_NAME")
            __chang_company_no(new_company_no, new_company_name, env_name)


@test_db_link
@catch_exceptions
def check_env_status(input_data=None, ui_expect=None):
    """
    环境检查
    :param input_data:
    :param ui_expect:
    :return:
    """
    env_name = input_data.get("env", "oracle")
    check_servers = input_data.get("servers", "pbs-task,pbs-server,rcce-task,amlps-server,amlcom-server,amlwl-server")
    config = amlConfig.get(env_name)
    logger.info(f"{config} 环境的系统参数是：{config}")
    logger.info(f"环境检查：env_name = {env_name}, ui_expect: {ui_expect}")
    result = check_server(env=env_name)
    logger.info(f"环境检查完成，执行结果是：{result}")
    check_result(result, check_servers)


@data_processing
@common_test_prepare
def common_query_method(input_data=None, ui_expect=None):
    """
    通用的页面查询和结果断言功能；匹配关键词：`下钻查询`
        若input中存在return关键字，则将获取页面目标化的关键列值，将其设置为全局变量。
        若存在click关键字，则进行点击下钻。若值未配置，会从期望中找，一般建议先配置期望检查，检查存在再进行下钻。
    :param input_data: {'菜单名称':'客户信息管理/个人户信息查询|客户信息管理/交易流水查询-交易申请',
                        'varg_flow_no': '实例编号',
                        '操作|C':'处理',
                        '客户名称':'张三',
                        '证件号码':'123456789012345678'}
    :param ui_expect:
    :return:
    """
    def __deal_input_data(raw_input_data):
        __return_columns = {}
        __click_column = {}
        __input_data = {}
        for k, v in raw_input_data.items():
            if k.startswith("varg_"):
                __return_columns[k] = v
            elif k.endswith("|C"):
                sk = k.split("|C")[0]
                __click_column[sk] = v
            else:
                __input_data[k] = v
        return __input_data, __return_columns, __click_column
    menu_name = input_data.get("菜单名称", None)
    input_data, return_columns, click_column = __deal_input_data(input_data)
    # 步骤1（可选）：打开菜单
    if menu_name:
        open_menu({'子系统名称': '反洗钱系统', '菜单名称': menu_name})
        if '-' in menu_name:
            tab_name = menu_name.split('-')[-1]
            for _ in range(3):
                tab_click(tab_name)
                time.sleep(1)
    # 步骤2：表达输入，点击查询
    arm_form_fill(input_data)
    # 步骤3：查询结果断言
    tablePage = check_table(input_data=input_data, ui_expect=ui_expect)
    # 步骤4（可选）：获取查询结果，把某一行某一列的值返回。
    if return_columns and tablePage:
        BladeVariable = Variable()
        for map_key, map_value in return_columns.items():
            cols_value = tablePage.get_target_cell({map_value: ''})
            col_value = cols_value[0] if cols_value else ''
            BladeVariable.set_variable(map_key, col_value)
            logger.info(f"设置全局变量：{map_key} = {col_value}")
    # 步骤5（可选）：查询结果，点击下钻，查看细节
    if click_column:
        tablePage.click_filter_cell(click_column)
        time.sleep(1)


@data_processing
@common_test_prepare
def common_detail_query(input_data=None, ui_expect=None):
    """
    二级页面查询：打开一级页面后点击详情，待二级页面打开后查询。匹配关键词：`下钻查询`
    :param input_data:
    :param ui_expect:
    :return:
    """
    # 下钻打开页面详情
    click_params = {}
    for k, v in input_data.items():
        if k.startswith('下钻|'):
            input_data.pop(k)
            k2 = k.split('|')[-1]
            click_params[k2] = v
    table = FE.table_new()
    table.click_cell(input_data=click_params, click_input=click_params)
    time.sleep(1)
    # 二级页面查询
    arm_form_fill(input_data)
    # 结果断言
    check_table(input_data=input_data, ui_expect=ui_expect)


@data_processing
def search_info(input_data=None, ui_expect=None):
    """
    旧的通用查询脚本！数据是读取excel中的
    :param input_data:
    :param ui_expect:
    :return:
    """
    logger.info(f'入参：{input_data}')
    logger.info(f'期望：{ui_expect}')
    varb = Variable()
    env = varb.get_variable('varg_db_type')
    current_path = varb.get_variable('varu_CurrentPath')
    project_web_path = os.path.join(current_path, "数据预埋\\基础功能")
    logger.info(f'blade环境信息：{env}, current_path: {current_path}, project_web_path: {project_web_path}')
    try:
        excel_name = input_data.get('xlsxName')
        sheet_name = input_data.get('sheetName')
        case_name = input_data.get('caseName')
        env_object = EnvConfig(env, config=amlConfig)
        url = env_object.url
        user = env_object.user
        pwd = env_object.pwd
        logger.info(f"test env, url: {url}, user: {user}, pwd: {pwd}")
        tab_name = ''
        # 检查是否需要执行sql脚本
        excel_path = getFilePath(excel_name + '.xlsx', project_web_path)    # 获取excel用例全路径
        sql_path = getFilePath(sheet_name + '.sql', project_web_path)       # 获取sql脚本全路径
        sql_handle_class(env, sql_path)
        # 读取用例的测试数据和期望值
        data_list = getExcelData(excel_name, sheet_name, case_name, excel_path)
        data = data_list[0]
        case_name = data[ExcelVarles.case_data]
        input_data_case = dataUtil(data[ExcelVarles.case_data])
        ui_expect_case = dataUtil(data[ExcelVarles.case_result])
        logger.info(f'case {case_name}  input_data: {input_data_case}')
        logger.info(f'case {case_name} expect_data: {ui_expect_case}')
        if '-' in sheet_name:
            sheet_name_list = sheet_name.split('-')
            sheet_name = sheet_name_list[0]
            tab_name = sheet_name_list[1]
        # 记录最新打开的菜单，切换菜单后退出重新登录，以清除页面的缓存，防止长时间运行用例导致浏览器崩溃
        last_sheet_name = varb.get_variable('varg_last_menu')
        logger.info(f"last_sheet_name: {last_sheet_name}")
        if sheet_name != last_sheet_name:
            sys_login(user, pwd, url)
            varb.set_variable('varg_last_menu', sheet_name)
        # 执行 查询脚本 进行测试
        """表单查询"""
        open_menu({'子系统名称': '反洗钱系统', '菜单名称': excel_name + '/' + sheet_name})
        if tab_name:
            for _ in range(3):
                tab_click(tab_name)
                time.sleep(1)
        arm_form_fill(input_data_case)
        # 结果断言
        check_table(input_data=input_data_case, ui_expect=ui_expect_case)
        return True
    except Exception as e:
        logger.error(f"error: {e}")
        error_info = traceback.format_exc()
        logger.error(f"format_exc: {error_info}")
        raise SeleniumError(f"UI test error: {e}")


@data_processing
@common_test_prepare
def common_export_data(input_data=None, ui_expect=None):
    """
    导出功能
    :param input_data:
    :param ui_expect:
    :return:
    """
    menu_name = input_data.pop("菜单名称")
    button_name = input_data.pop("导出类型", "导出全部行")
    filename = input_data.pop("文件名", None)
    if menu_name:
        filename = menu_name.split('/')[-1]
        # 步骤2（可选）：打开菜单
        open_menu({'子系统名称': '反洗钱系统', '菜单名称': menu_name})
        # 步骤3：表达输入，点击查询
        if len(input_data.keys()) > 0:
            arm_form_fill(input_data)
    if filename:
        # 步骤1：清理历史数据
        delete_dir_file(filename, DownPath)
    # 下载文件
    table_element = FE.table_new()
    table_element.export_row(filter=input_data, button_name=button_name)
    msg_confirm = FE.msg_box(timeout=3)
    msg_confirm.click_button("确认")
    # 检查下载结果
    if filename:
        check_file_exit(filename)